package com.weimob.mcloud.wechatwork.customer.facade.impl.process;

import com.alibaba.dubbo.config.annotation.Reference;
import com.weimob.mcloud.wechatwork.core.base.MultiResponse;
import com.weimob.mcloud.wechatwork.core.base.SingleRequest;
import com.weimob.mcloud.wechatwork.core.constant.CustomerCoreConstant;
import com.weimob.mcloud.wechatwork.core.constant.CustomerProcessConstant;
import com.weimob.mcloud.wechatwork.core.entity.privatesphere.PrivateSphere;
import com.weimob.mcloud.wechatwork.core.entity.relation.customer.*;
import com.weimob.mcloud.wechatwork.core.entity.relation.employee.Employee;
import com.weimob.mcloud.wechatwork.core.enums.customer.ExternalUserTypeEnum;
import com.weimob.mcloud.wechatwork.core.enums.employee.EmployeeActiveStatusEnum;
import com.weimob.mcloud.wechatwork.core.enums.employee.EmployeeStatusEnum;
import com.weimob.mcloud.wechatwork.core.service.customer.CustomerProcessService;
import com.weimob.mcloud.wechatwork.core.service.customer.CustomerStageRelationService;
import com.weimob.mcloud.wechatwork.core.service.customer.CustomerStageStatisticService;
import com.weimob.mcloud.wechatwork.core.service.customer.request.ChangeStageRelationRequest;
import com.weimob.mcloud.wechatwork.core.service.customer.request.GetSingleCustomerProcessRequest;
import com.weimob.mcloud.wechatwork.core.service.customer.request.QueryCustomerProcessRequest;
import com.weimob.mcloud.wechatwork.core.service.customer.request.QueryProcessByEmployeeRequest;
import com.weimob.mcloud.wechatwork.core.service.customer.response.GetSingleCustomerProcessResponse;
import com.weimob.mcloud.wechatwork.core.service.customer.response.QueryCustomerProcessResponse;
import com.weimob.mcloud.wechatwork.core.service.customer.response.QueryProcessByEmployeeResponse;
import com.weimob.mcloud.wechatwork.customer.convertor.customer.CustomerProcessRequestBuilder;
import com.weimob.mcloud.wechatwork.customer.mq.handler.externaluser.AddCorpExternaluserSecondHandler;
import com.weimob.mcloud.wechatwork.customer.service.user.exception.BizException;
import com.weimob.mcloud.wechatwork.customer.service.user.module.bo.process.*;
import com.weimob.mcloud.wechatwork.customer.service.user.module.dto.process.StageAuthDTO;
import com.weimob.mcloud.wechatwork.customer.service.user.module.dto.process.StageSetUpDTO;
import com.weimob.mcloud.wechatwork.customer.service.user.module.dto.process.StageStatisticDTO;
import com.weimob.mcloud.wechatwork.customer.third.PrivateSphereThird;
import com.weimob.mcloud.wechatwork.customer.third.core.CustomerServiceProxy;
import com.weimob.mcloud.wechatwork.customer.third.customer.CustomerThird;
import com.weimob.soa.common.response.SoaResponse;
import com.weimob.soa.common.utils.SoaUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.weimob.mcloud.wechatwork.customer.service.user.exception.BaseErrorCode.OPERATION_NOT_ALLOWED;
import static com.weimob.mcloud.wechatwork.customer.service.user.exception.BaseErrorCode.PROCESS_STAGE_OPERATION_CONFLICT;

/**
 * @author yuanhao
 * @date 2022/9/13 12:00
 */
@Slf4j
@Service
public class CustomerStageRelationFacade {

    @Autowired
    private PrivateSphereThird privateSphereThird;

    @Reference
    private CustomerStageRelationService stageRelationService;

    @Reference
    private CustomerStageStatisticService statisticService;

    @Reference
    private CustomerProcessService processService;

    @Resource
    private CustomerThird customerThird;

    @Resource
    CustomerProcessRequestBuilder requestBuilder;

    @Autowired
    private CustomerServiceProxy customerServiceProxy;

    @Autowired
    @Qualifier("commonThreadPool")
    private ThreadPoolTaskExecutor commonThreadPool;

    @Autowired
    private AddCorpExternaluserSecondHandler addCorpExternaluserSecondHandler;

    /**
     * 查询员工的流程列表(当前流程)
     *
     * @param stageAuthDTO stageAuthDTO
     * @return List<CurrentProcessListBO>
     */
    public List<CurrentProcessListBO> currentProcessList(StageAuthDTO stageAuthDTO) {
        //1.valid
        String userId = stageAuthDTO.getUserId();
        String customerId = stageAuthDTO.getCustomerId();
        Assert.notNull(userId, "userId不能为空");
        Assert.notNull(customerId, "customerId不能为空");
        //2.获取私域
        PrivateSphere privateSphere = privateSphereThird.fetch(stageAuthDTO.getBasicInfo(), Boolean.TRUE);

        //3.获取员工数据
        Employee employee = customerThird.queryEmployee(privateSphere, null, userId);
        if (Objects.isNull(employee) || StringUtils.isBlank(employee.getId())) {
            throw new BizException("未找到对应的员工信息");
        }

        //4.获取当前私域的所有流程数据（每个店铺最多10条流程）
        QueryCustomerProcessRequest queryCustomerProcessRequest = new QueryCustomerProcessRequest();
        queryCustomerProcessRequest.setPrivateSphere(privateSphere);
        SingleRequest<QueryCustomerProcessRequest> processReq = new SingleRequest<>(queryCustomerProcessRequest);
        QueryCustomerProcessResponse processResponse = SoaUtil.unpack(processService.queryAllBaseInfo(processReq));
        if (Objects.isNull(processResponse) || CollectionUtils.isEmpty(processResponse.getProcessList())) {
            return new ArrayList<>();
        }
        //4.1 转换成result
        List<CustomerProcess> processList = processResponse.getProcessList();
        List<CurrentProcessListBO> result = new ArrayList<>();
        processList.forEach(item -> {
            CurrentProcessListBO bo = new CurrentProcessListBO();
            bo.setProcessStatus(item.getStatusEnum().getCode());
            bo.setProcessId(item.getProcessId());
            bo.setProcessName(item.getProcessName());
            result.add(bo);
        });

        //5.获取此员工的所有流程权限
        Map<String, CustomerProcess> authMap = queryProcessByEmployee(employee, privateSphere);

        //5.1 如果为空 则表示此员工没有任何流程权限
        if (authMap.isEmpty()) {
            result.forEach(item -> item.setHaveAuth(Boolean.FALSE));
            return result;
        }

        //6.获取当前员工的所有流程数据
        CustomerStageRelation stageRelation = new CustomerStageRelation();
        stageRelation.setPrivateSphere(privateSphere);
        stageRelation.setCustomer(stageRelation.toCustomer(customerId));
        stageRelation.setEmployee(employee);
        stageRelation.setCurrentStage(Boolean.TRUE);
        SingleRequest<CustomerStageRelation> request = new SingleRequest<>(stageRelation);
        MultiResponse<CustomerStageRelation> multiResponse = SoaUtil.unpack(stageRelationService.fetchRelationList(request));

        Optional<CustomerStageRelation> first = Optional.empty();
        if (Objects.nonNull(multiResponse) && CollectionUtils.isNotEmpty(multiResponse.getDataList())) {
            //员工-流程关系
            List<CustomerStageRelation> dataList = multiResponse.getDataList();
            //找到最新的跟进流程
            first = dataList.stream().max(Comparator.comparing(CustomerStageRelation::getUpdateTime));
        }

        //7.当前流程字段赋值
        Optional<CustomerStageRelation> finalFirst = first;
        result.forEach(item -> {
            String processId = item.getProcessId();
            item.setHaveAuth(authMap.containsKey(processId));
            if (finalFirst.isPresent() && finalFirst.get().getProcessId().equals(processId)) {
                item.setCurrentProcess(Boolean.TRUE);
            }
        });

        return result;
    }

    /**
     * 设置流程
     *
     * @param stageSetUpDTO stageSetUpDTO
     * @return Boolean
     */
    public Boolean stageSetUp(StageSetUpDTO stageSetUpDTO) {
        //1.valid
        String processId = stageSetUpDTO.getProcessId();
        String userId = stageSetUpDTO.getUserId();
        String customerId = stageSetUpDTO.getCustomerId();
        String currentStageId = stageSetUpDTO.getCurrentStageId();
        String targetStageId = stageSetUpDTO.getTargetStageId();
        Assert.notNull(processId, "processId不能为空");
        Assert.notNull(targetStageId, "targetStageId不能为空");
        Assert.notNull(customerId, "customerId不能为空");
        Assert.notNull(userId, "txUserId不能为空");

        //2.查询当前阶段是否存在
        //2.1获取私域
        PrivateSphere privateSphere = privateSphereThird.fetch(stageSetUpDTO.getBasicInfo(), Boolean.TRUE);

        //校验流程，阶段是否存在
        checkStageIsValid(processId, currentStageId, targetStageId, privateSphere);

        //2.2获取此客户阶段详情
        CustomerStageRelation stageRelation = new CustomerStageRelation();
        stageRelation.setPrivateSphere(privateSphere);
        stageRelation.setCustomerProcess(stageRelation.toProcess(processId));
        stageRelation.setCurrentStage(Boolean.TRUE);
        stageRelation.setCustomer(stageRelation.toCustomer(customerId));
        SingleRequest<CustomerStageRelation> request = new SingleRequest<>(stageRelation);
        CustomerStageRelation relation = SoaUtil.unpack(stageRelationService.fetchStageRelation(request));
        //这个客户 在此流程下已经结束了，无法流转
        if (Objects.nonNull(relation) && Boolean.TRUE.equals(relation.getHasEnd())) {
            throw new BizException("当前客户的阶段为已结束，无法操作！");
        }
        //此客户在当前流程下 已经存在阶段数据，但是传参并没有当前阶段信息，则可能已经被流转了
        if (Objects.nonNull(relation) && Objects.isNull(currentStageId)) {
            throw new BizException("当前客户的阶段信息已流转，刷新页面后重试！");
        }
        //此客户当前流程的阶段 和 入参的当前阶段不一致，则可能被流转了
        if (Objects.nonNull(relation) && !relation.getStageId().equals(currentStageId)){
            throw new BizException(PROCESS_STAGE_OPERATION_CONFLICT);
        }

        //2.3 获取员工数据
        Employee employee = customerThird.queryEmployee(privateSphere, null, userId);
        if (Objects.isNull(employee) || StringUtils.isBlank(employee.getId())) {
            throw new BizException("未找到对应的员工信息");
        }
        EmployeeStatusEnum status = employee.getStatus();
        EmployeeActiveStatusEnum activeStatus = employee.getActiveStatus();
        if ( EmployeeActiveStatusEnum.INACTIVE.equals(activeStatus) || EmployeeStatusEnum.USER_UN_AUTHORIZATION.equals(status)) {
            throw new BizException("由于企业管理员调整了员工的权限，无法跟进客户。");
        }

        //2.4 判断此员工是否有此流程权限
        Boolean authResult = checkHaveAuth(employee, privateSphere, processId);
        if (Boolean.FALSE.equals(authResult)) {
            throw new BizException("您没有操作此流程的权限，请检查流程可见范围！");
        }

        //判断客户是否为微信客户，只有微信客户才可以设置阶段
        Customer customer = customerServiceProxy.fetchCustomer(customerId, null, privateSphere, ExternalUserTypeEnum.WECHAT_CUSTOMER);
        if (Objects.isNull(customer)) {
            throw new BizException(OPERATION_NOT_ALLOWED.getCode(), "当前客户类型为企业微信客户或者数据不存在！");
        }

        //转换
        CustomerStageRelation convertToRelation = convertToRelation(stageSetUpDTO, privateSphere, employee);
        //3.不存在则表示新增记录
        ChangeStageRelationRequest changeStageRelationRequest = new ChangeStageRelationRequest();
        if (Objects.isNull(relation)) {
            changeStageRelationRequest.setTargetStageRelation(convertToRelation);
        } else {
            //4.存在则更新
            changeStageRelationRequest.setCustomerStageRelation(relation);
            changeStageRelationRequest.setTargetStageRelation(convertToRelation);
        }
        SingleRequest<ChangeStageRelationRequest> saveRelationRequest = new SingleRequest<>(changeStageRelationRequest);
        stageRelationService.changeRelation(saveRelationRequest);

        //通知客搜
        if (!targetStageId.equals(currentStageId)) {
            commonThreadPool.execute(() -> noticeSearch(privateSphere, customerId));
        }

        return Boolean.TRUE;
    }

    /**
     *
     * 校验流程阶段是否有效
     * @param processId 流程id
     * @param currentStageId 当前阶段id
     * @param targetStageId 目标阶段id
     * @param privateSphere 私域
     */
    private void checkStageIsValid(String processId, String currentStageId, String targetStageId, PrivateSphere privateSphere) {
        //构建参数
        SingleRequest<GetSingleCustomerProcessRequest> singleRequest = requestBuilder.buildGetSingleRequest(privateSphere, null, processId);

        //查询该名称已存在
        SoaResponse<GetSingleCustomerProcessResponse, Void> single = processService.getSingle(singleRequest);
        GetSingleCustomerProcessResponse getSingleCustomerProcessResponse = SoaUtil.unpack(single);
        if (Objects.isNull(getSingleCustomerProcessResponse)) {
            throw new BizException("当前流程不存在，请刷新后重试！");
        }
        CustomerProcess customerProcess = getSingleCustomerProcessResponse.getCustomerProcess();
        if (Objects.isNull(customerProcess)) {
            throw new BizException("当前流程不存在，请刷新后重试！");
        }
        List<CustomerStage> customerStages = customerProcess.getCustomerStages();
        if (CollectionUtils.isEmpty(customerStages)) {
            throw new BizException("当前流程下没有阶段信息，请刷新后重试！");
        }
        Map<String, CustomerStage> map = customerStages.stream().collect(Collectors.toMap(CustomerStage::getStageId, i -> i, (t1, t2) -> t1));
        if (Objects.nonNull(currentStageId) && !map.containsKey(currentStageId)) {
            throw new BizException("当前阶段不存在，请刷新后重试！");
        }
        if (!map.containsKey(targetStageId)) {
            throw new BizException("当前阶段不存在，请刷新后重试！");
        }
    }

    private void noticeSearch(PrivateSphere privateSphere,String customerId){
        //2、获取客户基本信息
        Customer customer = customerServiceProxy.fetchCustomer(customerId, null, privateSphere);

        if (customer==null) {
            log.error("noticeSearch#fetchCustomer is null,customerId:{}", customerId);
            return;
        }
        Long superWid = customerThird.getSuperWid(privateSphere.getBosId(),
                customer.getExternalUserid(), privateSphere.getCorpId());
        if(Objects.isNull(superWid)){
            log.error("noticeSearch#fetchCustomer superWid is null,customerId:{}", customerId);
            return;
        }
        addCorpExternaluserSecondHandler.updateCustomerSearchMsg(superWid, privateSphere.getBosId(),
                privateSphere.getProductInstanceId(), privateSphere.getProductId());
    }

    /**
     * 转换成relation
     *
     * @param stageSetUpDTO stageSetUpDTO
     * @param privateSphere 私域
     * @param employee      员工
     * @return CustomerStageRelation
     */
    private CustomerStageRelation convertToRelation(StageSetUpDTO stageSetUpDTO, PrivateSphere privateSphere, Employee employee) {
        CustomerStageRelation targetRelation = new CustomerStageRelation();
        targetRelation.setPrivateSphere(privateSphere);
        CustomerProcess process = targetRelation.toProcess(stageSetUpDTO.getProcessId());
        process.setProcessName(stageSetUpDTO.getProcessName());
        targetRelation.setCustomerProcess(process);

        CustomerStage customerStage = targetRelation.toCustomerStage(stageSetUpDTO.getTargetStageId());
        customerStage.setStageName(stageSetUpDTO.getTargetStageName());
        targetRelation.setCustomerStage(customerStage);
        targetRelation.setEmployee(employee);
        targetRelation.setCustomer(targetRelation.toCustomer(stageSetUpDTO.getCustomerId()));
        targetRelation.setCurrentStage(Boolean.TRUE);
        targetRelation.setRemark(stageSetUpDTO.getRemark());
        targetRelation.setFileInfo(stageSetUpDTO.getFiles());
        if (CustomerProcessConstant.LAST_STAGE_NAME.equals(stageSetUpDTO.getTargetStageName())) {
            targetRelation.setHasEnd(Boolean.TRUE);
        }
        return targetRelation;
    }


    /**
     * 判断此员工是否有权限
     *
     * @param employee      员工
     * @param privateSphere 私域
     * @param processId     流程id
     */
    private Boolean checkHaveAuth(Employee employee, PrivateSphere privateSphere, String processId) {
        //1.获取此员工的所有流程
        Map<String, CustomerProcess> map = queryProcessByEmployee(employee, privateSphere);

        //2.结果处理
        if (map.isEmpty()) {
            return Boolean.FALSE;
        }

        //2.1 判断当前流程id是否有权限
        if (map.containsKey(processId)) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 获取当前流程下所有阶段关系数据
     *
     * @param stageAuthDTO stageAuthDTO
     * @return List<CurrentStageListBO>
     */
    public List<StageRelationDetailBO> currentStageList(StageAuthDTO stageAuthDTO) {
        String processId = stageAuthDTO.getProcessId();
        String userId = stageAuthDTO.getUserId();
        String customerId = stageAuthDTO.getCustomerId();
        Assert.notNull(customerId, "customerId不能为空");
        Assert.notNull(processId, "processId不能为空");
        Assert.notNull(userId, "userId不能为空");

        //1.获取私域
        PrivateSphere privateSphere = privateSphereThird.fetch(stageAuthDTO.getBasicInfo(), Boolean.TRUE);

        //2.获取当前流程下所有阶段关系数据
        CustomerStageRelation stageRelation = new CustomerStageRelation();
        stageRelation.setPrivateSphere(privateSphere);
        stageRelation.setCustomer(stageRelation.toCustomer(customerId));
        stageRelation.setCustomerProcess(stageRelation.toProcess(processId));
        SingleRequest<CustomerStageRelation> request = new SingleRequest<>(stageRelation);
        Map<String, Object> extInfo = request.getExtInfo();
        extInfo.put(CustomerCoreConstant.FETCH_STAGE, Boolean.TRUE);
        extInfo.put(CustomerCoreConstant.FETCH_EMPLOYEE, Boolean.TRUE);
        MultiResponse<CustomerStageRelation> multiResponse = SoaUtil.unpack(stageRelationService.fetchRelationList(request));

        //构建参数
        SingleRequest<GetSingleCustomerProcessRequest> singleRequest = requestBuilder.buildGetSingleRequest(privateSphere, null, processId);

        //获取所有的阶段信息
        SoaResponse<GetSingleCustomerProcessResponse, Void> single = processService.getSingle(singleRequest);
        GetSingleCustomerProcessResponse getSingleCustomerProcessResponse = SoaUtil.unpack(single);
        CustomerProcess customerProcess = getSingleCustomerProcessResponse.getCustomerProcess();
        if (Objects.isNull(customerProcess) || CollectionUtils.isEmpty(customerProcess.getCustomerStages())) {
            throw new BizException("当前流程数据不存在");
        }
        List<CustomerStage> customerStages = customerProcess.getCustomerStages();

        List<StageRelationDetailBO> result = new ArrayList<>();
        customerStages.forEach(item -> {
            StageRelationDetailBO stageRelationDetailBO = new StageRelationDetailBO();
            stageRelationDetailBO.setStageId(item.getStageId());
            stageRelationDetailBO.setStageName(item.getStageName());
            result.add(stageRelationDetailBO);
        });

        //3.结果处理
        if (Objects.isNull(multiResponse) || CollectionUtils.isEmpty(multiResponse.getDataList())) {
            return result;
        }

        List<CustomerStageRelation> dataList = multiResponse.getDataList();
        Map<String, CustomerStageRelation> map = dataList.stream().collect(Collectors.toMap(CustomerStageRelation::getStageId, i -> i, (k1, k2) -> k1));
        result.forEach(item -> {
            //convert
            CustomerStageRelation customerStageRelation = map.get(item.getStageId());
            if (Objects.nonNull(customerStageRelation)) {
                convertToCurrentStageListBO(item, customerStageRelation, userId);
            }

        });

        return result;
    }

    private StageRelationDetailBO convertToCurrentStageListBO(StageRelationDetailBO bo, CustomerStageRelation stageRelation, String userId) {
        bo.setFiles(stageRelation.getFileInfo());
        bo.setRemark(stageRelation.getRemark());
        bo.setFollowDate(stageRelation.getUpdateTime());
        bo.setProcessId(stageRelation.getProcessId());
        bo.setCurrentStage(stageRelation.getCurrentStage());
        bo.setStageId(stageRelation.getStageId());
        bo.setHasEnd(stageRelation.getHasEnd());
        CustomerStage customerStage = stageRelation.getCustomerStage();
        if (Objects.nonNull(customerStage)) {
            String stageName = customerStage.getStageName();
            bo.setStageName(stageName);
        }

        Employee employee = stageRelation.getEmployee();
        if (Objects.nonNull(employee)) {
            String employeeName = employee.getName();
            bo.setEmployeeName(employeeName);
        }

        return bo;
    }

    /**
     * 判断是否有此流程权限
     *
     * @param authDTO
     * @return
     */
    public Boolean isAuth(StageAuthDTO authDTO) {
        String processId = authDTO.getProcessId();
        String userId = authDTO.getUserId();
        Assert.notNull(processId, "processId不能为空");
        Assert.notNull(userId, "腾讯userId不能为空");

        //1.获取私域
        PrivateSphere privateSphere = privateSphereThird.fetch(authDTO.getBasicInfo(), Boolean.TRUE);

        //2.获取员工数据
        Employee employee = customerThird.queryEmployee(privateSphere, null, userId);
        if (Objects.isNull(employee)) {
            throw new BizException("未查询到对应的员工信息");
        }

        return checkHaveAuth(employee, privateSphere, processId);
    }

    private Map<String, CustomerProcess> queryProcessByEmployee(Employee employee, PrivateSphere privateSphere) {
        //查询
        QueryProcessByEmployeeRequest processByEmployeeRequest = new QueryProcessByEmployeeRequest();
        processByEmployeeRequest.setEmployee(employee);
        processByEmployeeRequest.setPrivateSphere(privateSphere);
        SingleRequest<QueryProcessByEmployeeRequest> request = new SingleRequest<>(processByEmployeeRequest);
        QueryProcessByEmployeeResponse response = SoaUtil.unpack(processService.queryProcessByEmployee(request));

        //结果处理
        HashMap<String, CustomerProcess> map = new HashMap<>();
        if (Objects.isNull(response) || CollectionUtils.isEmpty(response.getCustomerProcesses())) {
            return map;
        }
        List<CustomerProcess> customerProcesses = response.getCustomerProcesses();

        for (CustomerProcess customerProcess : customerProcesses) {
            map.put(customerProcess.getProcessId(), customerProcess);
        }
        return map;
    }

    /**
     * 获取此流程阶段的所有客户
     *
     * @param stageAuthDTO stageAuthDTO
     * @return PageResponse<StageCustomerListBO>
     */
    public List<StageCustomerListBO> fetchStageCustomerList(StageAuthDTO stageAuthDTO) {
        String stageId = stageAuthDTO.getStageId();
        String userId = stageAuthDTO.getUserId();
        Assert.notNull(stageId, "stageId不能为空");
        Assert.notNull(userId, "腾讯userId不能为空");

        //1.获取私域
        PrivateSphere privateSphere = privateSphereThird.fetch(stageAuthDTO.getBasicInfo(), Boolean.TRUE);

        //2.获取员工数据
        Employee employee = customerThird.queryEmployee(privateSphere, null, userId);
        if (Objects.isNull(employee)) {
            throw new BizException("未查询到对应的员工信息");
        }

        //3.获取此客户阶段详情
        CustomerStageRelation stageRelation = new CustomerStageRelation();
        stageRelation.setPrivateSphere(privateSphere);
        stageRelation.setCustomerStage(stageRelation.toCustomerStage(stageId));
        stageRelation.setEmployee(employee);
        SingleRequest<CustomerStageRelation> request = new SingleRequest<>(stageRelation);
        Map<String, Object> extInfo = request.getExtInfo();
        extInfo.put(CustomerCoreConstant.FETCH_CUSTOMER, Boolean.TRUE);
        MultiResponse<CustomerStageRelation> multiResponse = SoaUtil.unpack(stageRelationService.fetchToFollowList(request));

        //4.结果组装
        if (Objects.isNull(multiResponse) || CollectionUtils.isEmpty(multiResponse.getDataList())) {
            return new ArrayList<>();
        }

        List<CustomerStageRelation> dataList = multiResponse.getDataList();

        List<StageCustomerListBO> results = new ArrayList<>();
        dataList.forEach(item -> {
            Customer customer = item.getCustomer();
            if (Objects.nonNull(customer)) {
                StageCustomerListBO stageCustomerListBO = new StageCustomerListBO();
                stageCustomerListBO.setCustomerName(customer.getName());
                stageCustomerListBO.setExternalUserid(customer.getExternalUserid());
                stageCustomerListBO.setAvatar(customer.getAvatar());
                stageCustomerListBO.setCustomerId(customer.getId());
                results.add(stageCustomerListBO);
            }
        });

        return results;
    }

    public List<ProcessStatisticBO> fetchStatisticList(StageStatisticDTO stageStatisticDTO) {
        //1.获取私域
        PrivateSphere privateSphere = privateSphereThird.fetch(stageStatisticDTO.getBasicInfo(), Boolean.TRUE);

        String processId = stageStatisticDTO.getProcessId();

        //2.查询活跃度
        CustomerStageStatistic stageStatistic = new CustomerStageStatistic();
        stageStatistic.setPrivateSphere(privateSphere);
        stageStatistic.setCustomerProcess(stageStatistic.toProcess(processId));
        SingleRequest<CustomerStageStatistic> singleRequest = new SingleRequest<>(stageStatistic);
        MultiResponse<CustomerStageStatistic> multiResponse = SoaUtil.unpack(statisticService.fetchStatisticList(singleRequest));
        //3.查询所有的流程 阶段详情
        QueryCustomerProcessRequest queryCustomerProcessRequest = new QueryCustomerProcessRequest();
        queryCustomerProcessRequest.setPrivateSphere(privateSphere);
        SingleRequest<QueryCustomerProcessRequest> processReq = new SingleRequest<>(queryCustomerProcessRequest);
        QueryCustomerProcessResponse processResponse = SoaUtil.unpack(processService.queryAllIncludeStageBaseInfo(processReq));

        if (Objects.isNull(processResponse) || CollectionUtils.isEmpty(processResponse.getProcessList())) {
            return new ArrayList<>();
        }
        //按照processId过滤
        List<CustomerProcess> processList = processResponse.getProcessList();
        if (StringUtils.isNotBlank(processId)) {
            processList = processList.stream().filter(item -> processId.equals(item.getProcessId())).collect(Collectors.toList());
        }

        List<ProcessStatisticBO> result = new ArrayList<>();

        Map<String, CustomerStageStatistic> map = new HashMap<>(50);
        if (Objects.nonNull(multiResponse) && CollectionUtils.isNotEmpty(multiResponse.getDataList())) {
            //4.分组
            List<CustomerStageStatistic> dataList = multiResponse.getDataList();
            map = dataList.stream().collect(Collectors.toMap(CustomerStageStatistic::getStageId, i -> i, (k1, k2) -> k2));
        }

        //5.结果处理
        for (CustomerProcess process : processList) {
            ProcessStatisticBO processStatisticBO = new ProcessStatisticBO();
            processStatisticBO.setProcessName(process.getProcessName());
            processStatisticBO.setProcessId(process.getProcessId());

            List<CustomerStage> customerStages = process.getCustomerStages();
            List<StageStatisticBO> statisticList = new ArrayList<>();
            for (CustomerStage customerStage : customerStages) {
                StageStatisticBO bo = new StageStatisticBO();
                bo.setStageName(customerStage.getStageName());
                bo.setStageId(customerStage.getStageId());
                CustomerStageStatistic statistic = map.get(customerStage.getStageId());
                if (Objects.nonNull(statistic)) {
                    bo.setFollowTimes(statistic.getFollowTimes());
                    bo.setCurrentNum(statistic.getCurrentNum());
                    bo.setTotalNum(statistic.getTotalNum());
                }
                statisticList.add(bo);
            }
            processStatisticBO.setStatisticList(statisticList);
            result.add(processStatisticBO);
        }

        return result;
    }


    public StageRelationDetailBO stageRelationDetail(StageAuthDTO stageAuthDTO) {
        String stageId = stageAuthDTO.getStageId();
        String processId = stageAuthDTO.getProcessId();
        String customerId = stageAuthDTO.getCustomerId();
        //1.获取私域
        PrivateSphere privateSphere = privateSphereThird.fetch(stageAuthDTO.getBasicInfo(), Boolean.TRUE);

        //2.获取当前流程下所有阶段关系数据
        CustomerStageRelation stageRelation = new CustomerStageRelation();
        stageRelation.setPrivateSphere(privateSphere);
        stageRelation.setCustomerProcess(stageRelation.toProcess(processId));
        stageRelation.setCustomerStage(stageRelation.toCustomerStage(stageId));
        stageRelation.setCustomer(stageRelation.toCustomer(customerId));
        stageRelation.setCurrentStage(Boolean.TRUE);
        SingleRequest<CustomerStageRelation> request = new SingleRequest<>(stageRelation);
        Map<String, Object> extInfo = request.getExtInfo();
        extInfo.put(CustomerCoreConstant.FETCH_PROCESS, Boolean.TRUE);
        extInfo.put(CustomerCoreConstant.FETCH_STAGE, Boolean.TRUE);
        extInfo.put(CustomerCoreConstant.FETCH_CUSTOMER, Boolean.TRUE);
        MultiResponse<CustomerStageRelation> multiResponse = SoaUtil.unpack(stageRelationService.fetchRelationList(request));

        //3.结果处理
        if (Objects.isNull(multiResponse) || CollectionUtils.isEmpty(multiResponse.getDataList())) {
            return null;
        }

        //4.结果转换
        CustomerStageRelation customerStageRelation = multiResponse.getDataList().get(0);
        StageRelationDetailBO stageRelationDetailBO = new StageRelationDetailBO();
        return convertToCurrentStageListBO(stageRelationDetailBO, customerStageRelation, null);
    }

    /**
     * 删除process 或者 stage 通知客搜
     * @param privateSphere  私域
     * @param processId 流程id
     * @param stageId 阶段id
     */
    public void delProcessNoticeSearch(PrivateSphere privateSphere, String processId, String stageId) {
        if (Objects.isNull(privateSphere)) {
            log.error("delProcessNoticeSearch privateSphere is null");
            return;
        }
        if (StringUtils.isBlank(processId) && StringUtils.isBlank(stageId)) {
            log.error("delProcessNoticeSearch processId and stageId is null");
            return;
        }
        CustomerStageRelation stageRelation = new CustomerStageRelation();
        stageRelation.setPrivateSphere(privateSphere);
        if (StringUtils.isNotBlank(processId)) {
            stageRelation.setCustomerProcess(stageRelation.toProcess(processId));
        }
        if (StringUtils.isNotBlank(stageId)) {
            stageRelation.setCustomerStage(stageRelation.toCustomerStage(stageId));
        }
        stageRelation.setCurrentStage(Boolean.TRUE);
        stageRelation.setDeleted(1);
        SingleRequest<CustomerStageRelation> request = new SingleRequest<>(stageRelation);
        MultiResponse<CustomerStageRelation> multiResponse = SoaUtil.unpack(stageRelationService.fetchRelationList(request));
        //如果查到关联关系，则通知客搜
        if (Objects.nonNull(multiResponse) && CollectionUtils.isNotEmpty(multiResponse.getDataList())) {
            List<CustomerStageRelation> dataList = multiResponse.getDataList();
            dataList.forEach(item -> {
                commonThreadPool.execute(() -> noticeSearch(privateSphere, item.getCustomerId()));
            });
        }
    }
}
